package com.shijie.controller.app;

import java.math.BigDecimal;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.shijie.component.AppUserService;
import com.shijie.core.Result;
import com.shijie.core.ResultGenerator;
import com.shijie.core.annotation.NoLogin;
import com.shijie.service.UserOrdersService;
import com.shijie.utils.CommonUtil;


@RestController
@RequestMapping("/pay")
public class WxPayController {

    private static final Logger logger = LoggerFactory.getLogger(WxPayController.class);

    @Resource(name = "wxPayService")
    private WxPayService wxService;

    @Resource
    private AppUserService appUserService;

    @Resource
    private UserOrdersService userOrdersService;
    
    @Resource
    private WxPayConfig wxPayConfig;


    @PostMapping("/createOrder/{serialNum}")
    public Result createOrder(@PathVariable String serialNum) {
        try {
            WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = getWxPayUnifiedOrderRequest(serialNum);
            WxPayMpOrderResult wxPayMpOrderResult = this.wxService.createOrder(wxPayUnifiedOrderRequest);
            updateOrder(serialNum, wxPayMpOrderResult.getPackageValue());
            return ResultGenerator.success(wxPayMpOrderResult);
        } catch (WxPayException e) {
            logger.error("支付失败", e);
            return ResultGenerator.error("发起微信支付失败");
        }
    }


    private WxPayUnifiedOrderRequest getWxPayUnifiedOrderRequest(String serialNum) {
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setSpbillCreateIp(CommonUtil.getClientIp());
        request.setOpenid(appUserService.getCurrentUser().getOpenId());
        request.setLimitPay("no_credit");
        request.setNotifyURL(wxPayConfig.getNotifyUrl());
        request.setTotalFee(userOrdersService.selectPayAmount(serialNum).multiply(new BigDecimal(100)).intValue());
        request.setOutTradeNo(serialNum);
        if (serialNum.startsWith("ACTIVITY_")) {
            request.setBody("视界活动报名费用支付");
        } else if (serialNum.startsWith("GROUPON_")) {
            request.setBody("视界团购报名费用支付");
        } else {
            request.setBody("视界商品订单费用支付");
        }
        return request;
    }

    private void updateOrder(String serialNum, String packageValue) {
        userOrdersService.updatePayMsg(serialNum, packageValue);
    }


    /**
     * 支付回调
     */
    @PostMapping("/notify")
    @NoLogin
    public String parseRefundNotifyResult(@RequestBody String xmlData) {
        try {
            WxPayOrderNotifyResult wxPayOrderNotifyResult = this.wxService.parseOrderNotifyResult(xmlData);
            String outTradeNo = wxPayOrderNotifyResult.getOutTradeNo();
            Integer totalFee = userOrdersService.selectPayAmount(outTradeNo).multiply(new BigDecimal(100)).intValue();
            if (!totalFee.equals(wxPayOrderNotifyResult.getTotalFee())) {
                logger.error("支付回调失败:支付金额与订单不一致,支付流水号为:{},支付信息为", outTradeNo, xmlData);
                return WxPayNotifyResponse.fail("支付金额与订单不一致");
            }

            userOrdersService.paySuccessBySerialNum(outTradeNo);
            return WxPayNotifyResponse.success("OK");
        } catch (WxPayException e) {
            logger.error("支付回调失败", e);
            return WxPayNotifyResponse.fail(e.getReturnMsg());
        }
    }


}
